package com.zlkj.pro.modular.business.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.system.api.pojo.user.SysUserDTO;
import cn.stylefeng.roses.kernel.system.api.pojo.user.request.SysUserRequest;
import cn.stylefeng.roses.kernel.system.modular.user.service.SysUserService;
import com.anji.captcha.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zlkj.pro.core.consts.ProjectConstants;
import com.zlkj.pro.core.exception.BusinessException;
import com.zlkj.pro.core.util.ConvertUtil;
import com.zlkj.pro.core.util.LocalDateTimeUtils;
import com.zlkj.pro.modular.admin.entity.Config;
import com.zlkj.pro.modular.admin.entity.User;
import com.zlkj.pro.modular.admin.mapper.UserMapper;
import com.zlkj.pro.modular.admin.model.dto.DashboardDTO;
import com.zlkj.pro.modular.admin.model.dto.UserDTO;
import com.zlkj.pro.modular.admin.model.vo.UserVO;
import com.zlkj.pro.modular.admin.service.ConfigService;
import com.zlkj.pro.modular.admin.service.UsersService;
import com.zlkj.pro.modular.app.mapper.AppUserMapper;
import com.zlkj.pro.modular.business.entity.AgentEntity;
import com.zlkj.pro.modular.business.entity.ReportEntity;
import com.zlkj.pro.modular.business.mapper.DashboardMapper;
import com.zlkj.pro.modular.business.model.dto.AgentDTO;
import com.zlkj.pro.modular.business.model.vo.AgentVO;
import com.zlkj.pro.modular.business.service.AgentService;
import com.zlkj.pro.modular.business.service.DashboardService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
import java.util.*;

import static com.zlkj.pro.core.exception.enums.BusinessExceptionEnum.BUSINESS_EXCEPTION;

/**
 * @author liyang
 * @date 2024/4/6
 * @time 14:34
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class DashboardServiceImpl implements DashboardService {

    @Autowired
    private DashboardMapper dashboardMapper;

    @Autowired
    private UsersService usersService;

    @Autowired
    private AppUserMapper appUserMapper;

    @Autowired
    private Environment env;
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private ConfigService configService;

    @Autowired
    private AgentService agentService;


    public static void main(String[] args) {
        System.out.println(huanbi(2, 4));
    }

    // 两个Integer参数除法计算保留两位小数然后乘以100作为百分比
    public static Integer huanbi(Integer v1, Integer v2) {
        if (v1 == null || v2 == null) {
            return 0;
        }
        if (v2 == 0) {
            return 0;
        }
        double result = (double) (v1 - v2) / v2 * 100;
        return (int) result;
    }

    @Override
    public Map<String, Object> customer(DashboardDTO dto) {

        if (dto.getUserId() == null) {
            throw new BusinessException(BUSINESS_EXCEPTION, "UserId不能为空");
        }
        // 查询个人代理商信息
        Long agentId = appUserMapper.getAgentId(dto.getUserId());
        if (agentId != null && agentId != 0L) {
            dto.setAgentId(agentId);
        }

        // 角色赋值
        extracted(dto);
        // 客户分析数据-环比部分
        Map<String, Long> data = dashboardMapper.selectCustomer(dto);

        Map<String, Object> result = new HashMap<>();

        List<Map<String, Object>> monthMaps = new ArrayList<>();
        List<Map<String, Object>> yearMaps = new ArrayList<>();

        // 本月统计 报备客户数
        Map<String, Object> map1 = new HashMap<>();
        map1.put("name", "报备客户数");
        map1.put("number", data.get("count1"));
        map1.put("upDown", data.get("count1") >= data.get("count2"));
        map1.put("upDownValue", data.get("count2") == 0 ? "-" : huanbi(Math.toIntExact(data.get("count1")), Math.toIntExact(data.get("count2"))));
        // 本月统计 成交客户数
        Map<String, Object> map2 = new HashMap<>();
        map2.put("name", "成交客户数");
        map2.put("number", data.get("count3"));
        map2.put("upDown", data.get("count3") >= data.get("count4"));
        map2.put("upDownValue", data.get("count4") == 0 ? "-" : huanbi(Math.toIntExact(data.get("count3")), Math.toIntExact(data.get("count4"))));
        // 本月统计 新增客户数
        Map<String, Object> map3 = new HashMap<>();
        map3.put("name", "新增客户数");
        map3.put("number", data.get("count5"));
        map3.put("upDown", data.get("count5") >= data.get("count6"));
        map3.put("upDownValue", data.get("count6") == 0 ? "-" : huanbi(Math.toIntExact(data.get("count5")), Math.toIntExact(data.get("count6"))));

        // 本年统计 报备客户数
        Map<String, Object> map4 = new HashMap<>();
        map4.put("name", "报备客户数");
        map4.put("number", data.get("yearCount1"));
        map4.put("upDown", data.get("yearCount1") >= data.get("yearCount2"));
        map4.put("upDownValue", data.get("yearCount2") == 0 ? "-" : huanbi(Math.toIntExact(data.get("yearCount1")), Math.toIntExact(data.get("yearCount2"))));
        // 本年统计 成交客户数
        Map<String, Object> map5 = new HashMap<>();
        map5.put("name", "成交客户数");
        map5.put("number", data.get("yearCount3"));
        map5.put("upDown", data.get("yearCount3") >= data.get("yearCount4"));
        map5.put("upDownValue", data.get("yearCount4") == 0 ? "-" : huanbi(Math.toIntExact(data.get("yearCount3")), Math.toIntExact(data.get("yearCount4"))));
        // 本年统计 新增客户数
        Map<String, Object> map6 = new HashMap<>();
        map6.put("name", "新增客户数");
        map6.put("number", data.get("yearCount5"));
        map6.put("upDown", data.get("yearCount5") >= data.get("yearCount6"));
        map6.put("upDownValue", data.get("yearCount6") == 0 ? "-" : huanbi(Math.toIntExact(data.get("yearCount5")), Math.toIntExact(data.get("yearCount6"))));

        monthMaps.add(map1);
        monthMaps.add(map2);
        monthMaps.add(map3);
        yearMaps.add(map4);
        yearMaps.add(map5);
        yearMaps.add(map6);

        result.put("month", monthMaps);
        result.put("year", yearMaps);
        return result;
    }

    @Override
    public List<Map<String, Object>> customerByMonths(DashboardDTO dto) {
        if (dto.getUserId() == null) throw new BusinessException(BUSINESS_EXCEPTION, "userId不能为空");
        if (StringUtils.isEmpty(dto.getDataTimeStart()))
            throw new BusinessException(BUSINESS_EXCEPTION, "开始月份不能为空");
        if (StringUtils.isEmpty(dto.getDataTimeEnd()))
            throw new BusinessException(BUSINESS_EXCEPTION, "结束月份不能为空");
        if (dto.getDataType() == null) throw new BusinessException(BUSINESS_EXCEPTION, "请选择一个统计方式");

        // 角色赋值
        extracted(dto);

        List<Map<String, Object>> list = new ArrayList<>();
        if (dto.getDataType() == 1) {
            // 综合统计-报备客户数
            list = dashboardMapper.customerByMonthsType1(dto);
        } else if (dto.getDataType() == 2) {
            // 综合统计-成交客户数
            list = dashboardMapper.customerByMonthsType2(dto);
        } else if (dto.getDataType() == 3) {
            // 综合统计-新增客户数
            list = dashboardMapper.customerByMonthsType3(dto);
        }

        // 设置开始和结束的年月
        YearMonth start = YearMonth.of(Integer.parseInt(dto.getDataTimeStart().substring(0, 4)), Integer.parseInt(dto.getDataTimeStart().substring(5, 7)));
        YearMonth end = YearMonth.of(Integer.parseInt(dto.getDataTimeEnd().substring(0, 4)), Integer.parseInt(dto.getDataTimeEnd().substring(5, 7)));
        // 创建一个List来保存每个月份
        List<String> months = new ArrayList<>();

        // 使用while循环遍历从开始到结束的所有月份
        while (!start.isAfter(end)) {
            // 将YearMonth格式化为"YYYY-MM"字符串
            String monthStr = start.format(DateTimeFormatter.ofPattern("yyyy-MM"));
            // 添加到列表中
            months.add(monthStr);
            // 移动到下一个月
            start = start.plusMonths(1);
        }

        List<Map<String, Object>> result = new ArrayList<>();

        // 重新组装每个月份数据
        for (String month : months) {
            Boolean monthExist = false;
            if (CollectionUtils.isNotEmpty(list)) {
                monthExist = list.stream().anyMatch(map -> map.get("month").equals(month));
            }
            if (monthExist) {
                result.add(list.stream().filter(map -> map.get("month").equals(month)).findFirst().get());
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put("month", month);
                map.put("value", 0);
                result.add(map);
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> salesPerformance(DashboardDTO dto) {
        if (dto.getUserId() == null) throw new BusinessException(BUSINESS_EXCEPTION, "userId不能为空");
        // 角色赋值
        extracted(dto);
        // 查询超期时间
        LambdaQueryWrapper<Config> queryWrapper = new LambdaQueryWrapper<Config>();
        queryWrapper
                .eq(Config::getCode, "REPORT_END_REMIND")
                .eq(Config::getDelFlag, YesOrNotEnum.N.getCode());
        // 报备有效期提前提醒天数
        Integer reportEndRemind = Integer.parseInt(configService.getOne(queryWrapper).getValue());
        dto.setReportEndRemind(reportEndRemind);
        // 销售分析-近六月的新增报备数量
        List<Map<String, Object>> list1 = fixMonth(dashboardMapper.salesPerformance1(dto));
        // 销售分析-近六月的商谈中报备数量
//        List<Map<String, Object>> list2 = fixMonth(dashboardMapper.salesPerformance2(dto));
        List<Map<String, Object>> list2 = salesPerformance2Data(dashboardMapper.salesPerformance2Data(dto));
        // 销售分析-近六月的有效期临近报备数量
//        List<Map<String, Object>> list3 = fixMonth(dashboardMapper.salesPerformance3(dto));
        List<Map<String, Object>> list3 = salesPerformance3Data(dashboardMapper.salesPerformance3Data(dto));
        // 销售分析-近六月的成交报备数量
        List<Map<String, Object>> list4 = fixMonth(dashboardMapper.salesPerformance4(dto));

        // 汇总四个维度的结果
        List<Map<String, Object>> result = new ArrayList<>();
        Map<String, Object> countMap1 = new HashMap<>();
        Map<String, Object> countMap2 = new HashMap<>();
        Map<String, Object> countMap3 = new HashMap<>();
        Map<String, Object> countMap4 = new HashMap<>();
        Map<String, Object> countMap5 = new HashMap<>();
        Map<String, Object> countMap6 = new HashMap<>();

        result.add(countMap1);
        result.add(countMap2);
        result.add(countMap3);
        result.add(countMap4);
        result.add(countMap5);
        result.add(countMap6);

        for (int i = 0; i < 6; i++) {
            result.get(i).put("month", list1.get(i).get("month"));
            result.get(i).put("newCount", list1.get(i).get("count"));
            result.get(i).put("talkingCount", list2.get(i).get("count"));
            result.get(i).put("expirationCount", list3.get(i).get("count"));
            result.get(i).put("finishCount", list4.get(i).get("count"));
        }
        return result;
    }

    private List<Map<String, Object>> fixMonth(List<Map<String, Object>> list) {
        // 获取过去六个月的时间"yyyy-MM"
        List<String> months = new ArrayList<>();
        for (int i = 0; i < 6; i++) {
            LocalDate localDate = LocalDate.now().minusMonths(i);
            String month = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
            months.add(month);
        }
        // 升序排列
        months.sort(Comparator.naturalOrder());

        // 重新组装每个月份数据
        List<Map<String, Object>> result = new ArrayList<>();
        for (String month : months) {
            Boolean monthExist = false;
            if (CollectionUtils.isNotEmpty(list)) {
                monthExist = list.stream().anyMatch(map -> map.get("month").equals(month));
            }
            if (monthExist) {
                result.add(list.stream().filter(map -> map.get("month").equals(month)).findFirst().get());
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put("month", month);
                map.put("count", 0);
                result.add(map);
            }
        }
        return result;
    }


    private List<Map<String, Object>> salesPerformance2Data(List<ReportEntity> data){


        List<Map<String, Object>> result = new ArrayList<>();

        for (int i = 5; i >= 0; i--) {
            //当前时间减i个月
            LocalDateTime offset = LocalDateTimeUtil.offset(LocalDateTime.now(), -i, ChronoUnit.MONTHS);
            //日部分重置为1，只比较年月
            LocalDate date = LocalDateTimeUtil.ofDate(offset).withDayOfMonth(1);

            //跟审核时间、商谈中变更下一状态时间比较，偏移后的月份是否包含在内
            long count = data.stream().filter(f -> checkDate(date, f.getApproveDate(), f.getDiscussEndDate())).count();
            Map<String, Object> countMap = new HashMap<>();
            countMap.put("month", LocalDateTimeUtil.format(date, "yyyy-MM"));
            countMap.put("count", Integer.parseInt(String.valueOf(count)));

            result.add(countMap);

        }
        return result;

    }

    private List<Map<String, Object>> salesPerformance3Data(List<ReportEntity> data){


        List<Map<String, Object>> result = new ArrayList<>();

        for (int i = 5; i >= 0; i--) {
            //当前时间减i个月
            LocalDateTime offset = LocalDateTimeUtil.offset(LocalDateTime.now(), -i, ChronoUnit.MONTHS);
            //日部分重置为1，只比较年月
            LocalDate date = LocalDateTimeUtil.ofDate(offset).withDayOfMonth(1);

            //跟审核时间、商谈中变更下一状态时间比较，偏移后的月份是否包含在内
            long count = data.stream().filter(f -> checkDate(date, f.getSendMsgDate(), f.getDiscussEndDate())).count();
            Map<String, Object> countMap = new HashMap<>();
            countMap.put("month", LocalDateTimeUtil.format(date, "yyyy-MM"));
            countMap.put("count", Integer.parseInt(String.valueOf(count)));

            result.add(countMap);

        }
        return result;

    }

    private boolean checkDate(LocalDate checkDate, LocalDate beginDate, LocalDate endDate){
        //审核时间
        beginDate = beginDate.withDayOfMonth(1);
        //审核结束时间，为空重置为当前时间
        endDate = ObjectUtil.isNull(endDate) ? LocalDate.now() : endDate;
        endDate = endDate.withDayOfMonth(1);

        //偏移后的时间晚于审批时间 或 偏移后的时间早于审批结束时间
        return !checkDate.isBefore(beginDate) && !checkDate.isAfter(endDate);
    }

    @Override
    public UserVO selectUserInfo(Long userId) {
        UserDTO dto = new UserDTO();
        dto.setUserId(userId);
        UserVO vo = usersService.detail(dto);
        SysUserRequest sysUserRequest = new SysUserRequest();
        sysUserRequest.setUserId(userId);
        SysUserDTO currentUser = sysUserService.detail(sysUserRequest);
        Long roleId = currentUser.getGrantRoleIdList().get(0);

        // 获取代理商名称
        if (vo.getAgentId() != null) {
            vo.setAgentName(agentService.getById(vo.getAgentId()).getName());
        }
        if (ProjectConstants.ROLE_ID_BMSH_MANAGER.equals(roleId)) {
            vo.setRoleId(1L);
            vo.setSelectPre("");
            vo.setRoleName("BMSH管理者");
        } else if (ProjectConstants.ROLE_ID_BMSH_YG.equals(roleId)) {
            vo.setRoleId(2L);
            vo.setSelectPre("本地域");
            vo.setRoleName("BMSH营业者");
        } else if (ProjectConstants.ROLE_ID_AGENT_MANAGER.equals(roleId)) {
            vo.setRoleId(3L);
            vo.setSelectPre("");
            vo.setRoleName(vo.getAgentName() + "管理员");
        } else if (ProjectConstants.ROLE_ID_JL.equals(roleId)) {
            vo.setRoleId(4L);
            vo.setSelectPre("");
            vo.setRoleName(vo.getAgentName() + "经理");
        } else if (ProjectConstants.ROLE_ID_YG.equals(roleId)) {
            vo.setRoleId(5L);
            vo.setSelectPre("");
            vo.setRoleName(vo.getAgentName() + "员工");
        }else {
            vo.setRoleName("超级管理员");
        }
        return vo;
    }

    @Override
    public List<Map<String, Object>> seniorityUser(DashboardDTO dto) {
        if (dto.getUserId() == null) throw new BusinessException(BUSINESS_EXCEPTION, "userId不能为空");
        if (dto.getDataType() == null) throw new BusinessException(BUSINESS_EXCEPTION, "dataType不能为空");
        if (dto.getTimeRange() == null) throw new BusinessException(BUSINESS_EXCEPTION, "timeRange不能为空");
        // 角色赋值
        extracted(dto);
        // 销售排行（报备、成交数量）
        return fixSort(dashboardMapper.seniorityUser(dto));
    }

    @Override
    public List<Map<String, Object>> seniorityAgent(DashboardDTO dto) {
        if (dto.getUserId() == null) throw new BusinessException(BUSINESS_EXCEPTION, "userId不能为空");
        if (dto.getDataType() == null) throw new BusinessException(BUSINESS_EXCEPTION, "dataType不能为空");
        if (dto.getTimeRange() == null) throw new BusinessException(BUSINESS_EXCEPTION, "timeRange不能为空");
        // 角色赋值
        extracted(dto);
        // 代理商排行（报备、成交数量）
        return fixSort(dashboardMapper.seniorityAgent(dto));
    }

    @Override
    public List<Map<String, Object>> seniorityRegion(DashboardDTO dto) {
        if (dto.getUserId() == null) throw new BusinessException(BUSINESS_EXCEPTION, "userId不能为空");
        if (dto.getDataType() == null) throw new BusinessException(BUSINESS_EXCEPTION, "dataType不能为空");
        if (dto.getTimeRange() == null) throw new BusinessException(BUSINESS_EXCEPTION, "timeRange不能为空");
        // 角色赋值
        extracted(dto);
        // 地域排行（报备、成交数量）
        return fixSort(dashboardMapper.seniorityRegion(dto));
    }

    //添加排名
    private List<Map<String, Object>> fixSort(List<Map<String, Object>> maps) {
        if (CollectionUtils.isEmpty(maps)) {
            return maps;
        }
        maps.forEach(map -> {
            map.put("sort", maps.indexOf(map) + 1);
        });
        return maps;
    }


    private void extracted(DashboardDTO dto) {
        SysUserRequest sysUserRequest = new SysUserRequest();
        sysUserRequest.setUserId(dto.getUserId());
        SysUserDTO currentUser = sysUserService.detail(sysUserRequest);
        Long roleId = currentUser.getGrantRoleIdList().get(0);
        if (ProjectConstants.ROLE_ID_BMSH_MANAGER.equals(roleId)) {
            dto.setRoleId(1);
        } else if (ProjectConstants.ROLE_ID_BMSH_YG.equals(roleId)) {
            dto.setRoleId(2);
        } else if (ProjectConstants.ROLE_ID_AGENT_MANAGER.equals(roleId)) {
            dto.setRoleId(3);
        } else if (ProjectConstants.ROLE_ID_JL.equals(roleId)) {
            dto.setRoleId(4);
        } else if (ProjectConstants.ROLE_ID_YG.equals(roleId)) {
            dto.setRoleId(5);
        }
    }

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<AgentVO> findAgentList(AgentDTO dto) {
        // 获取用户代理商 ID
        User userVo = userMapper.selectById(LoginContext.me().getLoginUser().getUserId());
        // 如果当前用户有所属代理商 那么下拉列表也只查看自己的所在的代理商
        LambdaQueryWrapper<AgentEntity> queryWrapper = Wrappers.lambdaQuery();
        //queryWrapper.eq(AgentEntity::getStatusFlag, 1);
        if (userVo.getAgentId() != null) {
            queryWrapper.eq(AgentEntity::getId, userVo.getAgentId());
        }

        if (StrUtil.isNotBlank(dto.getRegion())) {
            queryWrapper.eq(AgentEntity::getRegion, dto.getRegion());
        } else {
            // 如果当前用户有所属地域 那只能查看自己所在地域的代理商
            if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(userVo.getRegion())) {
                queryWrapper.in(AgentEntity::getRegion, Arrays.asList(userVo.getRegion().split(",")));
            }
        }


        queryWrapper.orderByDesc(AgentEntity::getCreateTime);
        List<AgentEntity> productInfoEntityList = agentService.list(queryWrapper);
        return ConvertUtil.turn(productInfoEntityList, AgentVO.class);
    }

}
